package question08;

/**
 * @author yuan
 * @date 2021/12/14
 */

/**
 * 问题：
 *      将字符串转换成一个 32 位有符号整数
 * 思路：
 *      1、定义字符串扫描索引，遍历字符串，一直到 array[index] != ' '的情况(去除先导空格)
 *      2、判断 array[index] 字符，如果为 '-'则为负数，为 '+'，或不写都为 正数
 *      3、变量 res 用于接收,array[index] - '0' 就可以获得当前字符 firstNum，
 *      res = isPositiveNum ? res * 10 + firstNum : res * 10 - firstNum
 *      就可以实现正负数的判断 以及 res 累加
 *      4、接收的时候先进行 int 越界校验，正数的可能越界情况，因为即将进行的 *10 操作，
 *      所以当 reverseValue > Integer.MAX_VALUE / 10 越界 或 reverseValue 与 int 最大值
 *      的十分之一相等并且 firstNum > int 最大值的个位数时越界，即
 *      reverseValue == Integer.MAX_VALUE / 10 && firstNum > Integer.MAX_VALUE % 10
 *      负数同理
 */
public class Solution {

    public static void main(String[] args) {
        System.out.println(new Solution().myAtoi("42"));
        System.out.println(new Solution().myAtoi("   -42"));
        System.out.println(new Solution().myAtoi("4193 with words"));
        System.out.println(new Solution().myAtoi("words and 987"));
        System.out.println(new Solution().myAtoi("-91283472332"));
    }

    /**
     * 将字符串转换成一个 32 位有符号整数
     * @param s
     * @return
     */
    public int myAtoi(String s) {

        // 字符串长度
        int length = s.length();
        // 字节数组
        char[] array = s.toCharArray();
        // 扫描索引
        int index = 0;

        // 去除前导空格
        while (index < length && array[index] == ' ') index++;

        // 全部为空格
        if (index == length) return 0;

        // 第一个字符
        char firstChar = array[index];
        // 是否为正数
        boolean isPositiveNum = firstChar != '-';

        // 读到正数或为负数，则后移
        if (firstChar == '+' || !isPositiveNum) index++;

        // 转换数字字符
        int res = 0;
        while (index < length) {

            // 弹出当前字符
            char currChar = array[index];
            // 合法性校验
            if (currChar > '9' || currChar < '0') break;
            int firstNum = currChar - '0';
            // 正数校验
            if (res  > Integer.MAX_VALUE / 10
                    || res == Integer.MAX_VALUE / 10 &&
                    firstNum > Integer.MAX_VALUE % 10) return Integer.MAX_VALUE;
            // 负数校验
            if (res  < Integer.MIN_VALUE / 10
                    || res == Integer.MIN_VALUE / 10 &&
                    firstNum < Integer.MIN_VALUE % 10) return Integer.MIN_VALUE;

            // 推入
            res = isPositiveNum ? res * 10 + firstNum : res * 10 - firstNum;
            index++;
        }
        return res;
    }

}
